package com.ut.animator;

import com.ut.richpath.RichPath;
import com.ut.richpath.util.JsonUtil;
import com.ut.richpath.util.LogUtil;
import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorGroup;
import ohos.agp.animation.AnimatorProperty;
import ohos.agp.animation.AnimatorValue;

import java.util.ArrayList;
import java.util.List;

public class RichPathAnimator {

    public final static int INFINITE = -1;
    public final static RepeatMode NONE = RepeatMode.None;
    public final static RepeatMode RESTART = RepeatMode.Restart;
    public final static RepeatMode REVERSE = RepeatMode.Reverse;

    long duration = -1L;
    long startDelay = -1L;
//    var interpolator: Interpolator? = null
    RepeatMode repeatMode = RepeatMode.None;
    int repeatCount;
    AnimationListener animationListener;

    private List<AnimationBuilder> animationBuilders = new ArrayList<>();

    private AnimatorGroup animatorSet;

    private RichPathAnimator prev;
    private RichPathAnimator next;

    public static AnimationBuilder animate(RichPath path){
        RichPathAnimator viewAnimator = new RichPathAnimator();
        return viewAnimator.addAnimationBuilder(path);
    }

    public static AnimationBuilder animate(List<RichPath> path){
        RichPathAnimator viewAnimator = new RichPathAnimator();
        return viewAnimator.addAnimationBuilder(path);
    }

    public AnimationBuilder addAnimationBuilder(RichPath path) {
        AnimationBuilder animationBuilder = new AnimationBuilder(this, path);
        animationBuilders.add(animationBuilder);
        return animationBuilder;
    }

    public AnimationBuilder addAnimationBuilder(List<RichPath> paths) {
        AnimationBuilder animationBuilder = new AnimationBuilder(this, paths);
        animationBuilders.add(animationBuilder);
        return animationBuilder;
    }

    public AnimationBuilder thenAnimate(RichPath path) {
        RichPathAnimator nextRichPathAnimator = new RichPathAnimator();
        this.next = nextRichPathAnimator;
        nextRichPathAnimator.prev = this;
        return nextRichPathAnimator.addAnimationBuilder(path);
    }

    public AnimationBuilder thenAnimate(List<RichPath> paths) {
        RichPathAnimator nextRichPathAnimator = new RichPathAnimator();
        this.next = nextRichPathAnimator;
        nextRichPathAnimator.prev = this;
        return nextRichPathAnimator.addAnimationBuilder(paths);
    }

    private AnimatorGroup createAnimatorSet(){
        List<AnimatorValue> animators = new ArrayList<>();
        LogUtil.i("animationBuilders is null: %b", animationBuilders==null);
        for (AnimationBuilder animationBuilder : animationBuilders) {
            List<AnimatorValue> animatorList = animationBuilder.getAnimators();
            animators.addAll(animatorList);
            LogUtil.i("@animator list size: %d", animatorList.size());
            if (repeatMode != RepeatMode.None) {
                animationBuilder.repeatMode(repeatMode);
            }
            animationBuilder.repeatCount(repeatCount);
        }
        AnimatorGroup animatorSet = new AnimatorGroup();
        LogUtil.i("animators size: %d", animators.size());
        AnimatorValue[] animatorValues = listToArray(animators);
//        LogUtil.i("animators: %s", JsonUtil.toJson(animatorValues));
        animatorSet.runParallel(animatorValues);

        if (duration != -1L) {
            animatorSet.setDuration(duration);
        }
        if (startDelay != -1L) {
            animatorSet.setDelay(startDelay);
        }
//        interpolator?.let { animatorSet.interpolator = it }
        animatorSet.setStateChangedListener(new Animator.StateChangedListener() {
            @Override
            public void onStart(Animator animator) {
                if (animationListener!=null)animationListener.onStart();
            }

            @Override
            public void onStop(Animator animator) {

            }

            @Override
            public void onCancel(Animator animator) {

            }

            @Override
            public void onEnd(Animator animator) {
                if (animationListener!=null)animationListener.onStop();
                if (next!=null){
                    next.prev = null;
                    next.start();
                }
            }

            @Override
            public void onPause(Animator animator) {

            }

            @Override
            public void onResume(Animator animator) {

            }
        });

        return animatorSet;
    }

    private AnimatorValue[] listToArray(List<AnimatorValue> list){
        AnimatorValue[] array = new AnimatorValue[list.size()];
        for (int i=0; i<list.size(); i++)array[i] = list.get(i);
        return array;
    }

    public RichPathAnimator start(){
        LogUtil.i("animator is running, prev is null：%b, next is null: %b", prev==null, next==null);
        if (prev!=null){
            RichPathAnimator richPathAnimator = prev.start();
            if (richPathAnimator!=null){
                richPathAnimator.animatorSet = richPathAnimator.createAnimatorSet();

                LogUtil.i("animator set start");
                richPathAnimator.animatorSet.start();
            }
            LogUtil.i("class: %s, animator set is null: %b", richPathAnimator.toString(), richPathAnimator.animatorSet==null);
        }
        if (next==null){
            createAnimatorSet().start();
        }
        return this;
    }

    public void cancel() {
        if (animatorSet!=null&&animatorSet.isRunning()){
            animatorSet.cancel();
        }

        if (next!=null){
            next.cancel();
            next = null;
        }
    }

}
